﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Spring.Transaction.Interceptor;

using BOSS.Framework;
using BOSS.Domain.Customers;
using BOSS.Domain.Security;
using BOSS.Dao.Customers;
using BOSS.Dao.Security;
using BOSS.Service.Customers;
using BOSS.Service.Security;

namespace BOSS.Service.Implements.Customers
{
    public class CustomerService : EntityServiceWithSN<Customer, int, ICustomerDao>, ICustomerService
    {
        /// <summary>
        /// 获取 / 设置 系统账号 DAO
        /// </summary>
        public IAccountDao AccountDao { get; set; }

        /// <summary>
        /// 获取 / 设置 账号服务
        /// </summary>
        public IAccountService AccountService { get; set; }

        /// <summary>
        /// 获取 / 设置 客户账户 DAO
        /// </summary>
        public ICustomerAccountDao CustomerAccountDao { get; set; }

        /// <summary>
        /// 获取 / 设置 会员卡 DAO
        /// </summary>
        public ICustomerCardDao CustomerCardDao { get; set; }

        /// <summary>
        /// 获取 客户序列号前缀
        /// </summary>
        public override string SerialNumberPrefix
        {
            get { return "CUS"; }
        }

        /// <summary>
        /// 保存客户
        /// </summary>
        /// <param name="entity"></param>
        [Transaction(ReadOnly=false)]
        public override void SaveOrUpdate(Customer entity)
        {
            this.Prepare(entity);
            if (entity.Id == 0)
            {
                entity.SerialNumber = this.GenerateSerialNumber();
            }

            base.SaveOrUpdate(entity);
        }

        #region ICustomerService 成员

        /// <summary>
        /// 保存客户账户
        /// </summary>
        /// <param name="customerAccount"></param>
        /// <returns></returns>
        [Transaction(ReadOnly = false)]
        public int SaveCustomerAccount(CustomerAccount customerAccount)
        {
            this.Prepare(customerAccount);
            return this.CustomerAccountDao.Save(customerAccount);
        }

        /// <summary>
        /// 获取客户账户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public CustomerAccount FindCustomerAccountById(int id)
        {
            return this.CustomerAccountDao.FindById(id);
        }

        /// <summary>
        /// 获取会员卡
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public CustomerCard FindCustomerCardById(int id)
        {
            return this.CustomerCardDao.FindById(id);
        }

        /// <summary>
        /// 获取会员卡
        /// </summary>
        /// <param name="cardNumber"></param>
        /// <returns></returns>
        public CustomerCard FindCustomerCardByCardNumber(string cardNumber)
        {
            return this.CustomerCardDao.FindByCardNumber(cardNumber);
        }

        /// <summary>
        /// 保存或修改会员卡
        /// </summary>
        /// <param name="customerCard"></param>
        [Transaction(ReadOnly = false)]
        public void SaveOrUpdateCustomerCard(CustomerCard customerCard)
        {
            this.Prepare(customerCard);
            if (customerCard.Id == 0)
            {
                customerCard.Password = PasswordCryptor.Default.Encrypt("112233");
                customerCard.State = CustomerCardState.New;
            }
            this.CustomerCardDao.SaveOrUpdate(customerCard);
        }

        /// <summary>
        /// 会员卡流程
        /// </summary>
        /// <param name="customerCard"></param>
        /// <param name="action"></param>
        [Transaction(ReadOnly = false)]
        public void CustomerCardWorkflow(CustomerCard customerCard, CustomerCardFlowAction action)
        {
            if (customerCard.WorkFlowRecords == null)
            {
                customerCard.WorkFlowRecords = new List<CustomerCardFlowRecord>();
            }

            CustomerCardFlowRecord workflowRecord = new CustomerCardFlowRecord() 
            {
                CustomerCard = customerCard,
                OldState = customerCard.State
            };

            this.Prepare(workflowRecord);
            switch (action)
            {
                case CustomerCardFlowAction.Activate:
                    if (customerCard.State == CustomerCardState.New || customerCard.State == CustomerCardState.Lost)
                    {
                        workflowRecord.NewState = CustomerCardState.Activated;
                        workflowRecord.Action = CustomerCardFlowAction.Activate;
                        customerCard.WorkFlowRecords.Add(workflowRecord);
                        customerCard.ActivationDate = DateTime.Now;
                        customerCard.State = CustomerCardState.Activated;
                    }
                    break;
                case CustomerCardFlowAction.Lose:
                    workflowRecord.NewState = CustomerCardState.Lost;
                    workflowRecord.Action = CustomerCardFlowAction.Lose;
                    customerCard.WorkFlowRecords.Add(workflowRecord);
                    customerCard.State = CustomerCardState.Lost;
                    break;
                case CustomerCardFlowAction.Delete:
                    workflowRecord.NewState = CustomerCardState.Deleted;
                    workflowRecord.Action = CustomerCardFlowAction.Delete;
                    customerCard.WorkFlowRecords.Add(workflowRecord);
                    customerCard.State = CustomerCardState.Deleted;
                    break;
                default:
                    break;
            }

            this.CustomerCardDao.Update(customerCard);
        }

        #endregion

        private void Prepare<T>(T entity) where T : DomainEntity<int>
        {
            DateTime now = DateTime.Now;
            if (entity.Id == 0)
            {
                entity.Creator = this.AccountService.CurrentAccount;
                entity.CreateTime = now;
            }
            entity.Updator = this.AccountService.CurrentAccount;
            entity.UpdateTime = now;
        }
    }
}
